
// object_json.js
// 手动解析 JSON 字符串的简单实现
function parseJSON(jsonString) {
    // 去除可能存在的多余空格
    jsonString = jsonString.trim();

    // 如果是对象，解析
    if (jsonString[0] === '{' && jsonString[jsonString.length - 1] === '}') {
        const obj = {};
        jsonString = jsonString.slice(1, jsonString.length - 1).trim(); // 去掉两边的大括号

        // 按照键值对解析
        const pairs = jsonString.split(','); // 按逗号分隔每个键值对
        for (const pair of pairs) {
            const [key, value] = pair.split(':').map(s => s.trim());
            obj[key.replace(/"/g, '')] = value.replace(/"/g, ''); // 去掉引号并赋值
        }
        return obj;
    }

    // 如果是数组，解析
    if (jsonString[0] === '[' && jsonString[jsonString.length - 1] === ']') {
        const arr = [];
        jsonString = jsonString.slice(1, jsonString.length - 1).trim(); // 去掉两边的中括号

        const elements = jsonString.split(','); // 按逗号分隔每个元素
        for (const element of elements) {
            arr.push(element.trim().replace(/"/g, '')); // 去掉引号并放入数组
        }
        return arr;
    }

    // 如果是基本类型，直接返回
    if (jsonString === 'null') return null;
    if (jsonString === 'true') return true;
    if (jsonString === 'false') return false;
    if (!isNaN(jsonString)) return parseFloat(jsonString);

    // 如果无法解析，返回 undefined
    return undefined;
}
class TextEncoder {
    encode(str) {
        const utf8 = [];
        for (let i = 0; i < str.length; i++) {
            let charCode = str.charCodeAt(i);
            try {
                if (charCode < 0x80) {
                    utf8.push(charCode);
                } else if (charCode < 0x800) {
                    utf8.push(0xc0 | (charCode >> 6));
                    utf8.push(0x80 | (charCode & 0x3f));
                } else if (charCode < 0xd800 || charCode >= 0xe000) {
                    utf8.push(0xe0 | (charCode >> 12));
                    utf8.push(0x80 | ((charCode >> 6) & 0x3f));
                    utf8.push(0x80 | (charCode & 0x3f));
                } else {
                    // surrogate pair
                    i++;
                    if (i >= str.length) {
                        console.error("Incomplete surrogate pair in input string.");
                        return new Uint8Array(0); // Return empty array in case of error
                    }
                    charCode = 0x10000 + (((charCode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
                    utf8.push(0xf0 | (charCode >> 18));
                    utf8.push(0x80 | ((charCode >> 12) & 0x3f));
                    utf8.push(0x80 | ((charCode >> 6) & 0x3f));
                    utf8.push(0x80 | (charCode & 0x3f));
                }
            } catch (error) {
                console.error("Encoding error for character:", String.fromCharCode(charCode), "Error:", error.message);
                return new Uint8Array(0); // Return empty array in case of encoding error
            }
        }
        return new Uint8Array(utf8);
    }
}

class TextDecoder {
    decode(uint8Array) {
        let str = "";
        let i = 0;
        while (i < uint8Array.length) {
            const byte1 = uint8Array[i++];
            if (byte1 < 0x80) {
                str += String.fromCharCode(byte1);
            } else if (byte1 < 0xe0) {
                const byte2 = uint8Array[i++];
                str += String.fromCharCode(((byte1 & 0x1f) << 6) | (byte2 & 0x3f));
            } else if (byte1 < 0xf0) {
                const byte2 = uint8Array[i++];
                const byte3 = uint8Array[i++];
                str += String.fromCharCode(((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6) | (byte3 & 0x3f));
            } else {
                const byte2 = uint8Array[i++];
                const byte3 = uint8Array[i++];
                const byte4 = uint8Array[i++];
                const codePoint = (((byte1 & 0x07) << 18) | ((byte2 & 0x3f) << 12) | ((byte3 & 0x3f) << 6) | (byte4 & 0x3f)) - 0x10000;
                str += String.fromCharCode(0xd800 | (codePoint >> 10));
                str += String.fromCharCode(0xdc00 | (codePoint & 0x3ff));
            }
        }
        return str;
    }
}
// 假设内存有足够的空间，最大分配大小为 64KB
const MAX_MEMORY_SIZE = 640 * 1024;  // 64KB
var memory;
var imported = {
    memory: new WebAssembly.Memory({ initial: 20 }), // 增加初始内存大小
    abort: function (a, b, c, d) { console.log("abort"); },
    "performance.now": () => performance.now(),  // 提供 performance.now 的替代实现
    JSON_parse: (ptr) => {
        const decoder = new TextDecoder('utf-8');
        const byteArray = new Uint8Array(memory.buffer, ptr);
        let end = byteArray.length;

        // 查找终止符 0 或多余的空字节，去掉所有尾部无效字节
        while (end > 0 && byteArray[end - 1] === 0) {
            end--;
        }

        const jsonString = decoder.decode(byteArray.subarray(0, end));

        // 输出解码的字符串，帮助调试
        console.log("Decoded JSON string:", jsonString);

        // 手动反序列化 JSON 字符串
        return parseJSON(jsonString);
    },
    JSON_stringify: (obj) => {
        const jsonString = JSON.stringify(obj);
        const encoder = new TextEncoder();
        const jsonBuffer = encoder.encode(jsonString);
    
                // 确保内存大小足够存储数据
        if (jsonBuffer.length + 1 > MAX_MEMORY_SIZE) {
            console.error("Memory overflow: Data is too large to fit into predefined memory.");
            return 0;  // 返回一个无效指针
        }

        // 在已知内存区域中分配空间，可以选择一个具体位置来存放数据
        const ptr = 0;  // 可以选择从内存的起始位置开始存储，或选择某个固定偏移量
        // 动态分配内存
        //const ptr = memory.grow(Math.ceil((jsonBuffer.length + 1) / 65536)); // 扩展内存
        // 计算需要的内存页数，确保足够存储数据
        /*
        const requiredPages = Math.ceil((jsonBuffer.length + 1) / 65536); // 每页64KB
        const previousPages = memory.buffer.byteLength / 65536; // 当前分配的内存页数
        const additionalPages = requiredPages - previousPages;

        if (additionalPages > 0) {
            memory.grow(additionalPages); // 动态扩展内存
        }

        // 确定写入的起始位置
        const ptr = memory.buffer.byteLength - jsonBuffer.length - 1;
        */


        const jsonBufferWithNull = new Uint8Array(memory.buffer, ptr, jsonBuffer.length + 1);
        jsonBufferWithNull.set(jsonBuffer);
        jsonBufferWithNull[jsonBuffer.length] = 0; // 终止符
    
        if (jsonBufferWithNull.length > memory.buffer.byteLength - ptr) {
            console.error("Memory write out of bounds error!");
            return;
        }
        return ptr; // 返回正确的内存地址
    }
    
};
function parseStudentJson(jsonString) {
    // 解析 JSON 字符串
    const student = JSON.parse(jsonString);

    // 打印学生信息的每个属性
    console.log("Student Information:");
    console.log(`ID: ${student.id}`);
    console.log(`Name: ${student.name}`);
    console.log(`Age: ${student.age}`);
    console.log(`Grade: ${student.grade}`);
    console.log(`Time: ${student.time}`);
    
    // 返回解析出的学生对象
    return student;
}
function test(file, func, ...args) {
    const bytes = readbuffer(file);
    const mod = new WebAssembly.Module(bytes);
    const instance = new WebAssembly.Instance(mod, { env: imported });
    memory = instance.exports.memory;

    // 定义学生信息对象
    const studentInfo = {
        id: 1,
        name: "Bob",
        age: 22,
        grade: 4,
        time: 0.0 
    };

    // 将学生信息对象序列化为 JSON 字符串并写入 WebAssembly 内存
    const inputStudentPtr = imported.JSON_stringify(studentInfo);
    //const inputStudentPtr = JSON.stringify(studentInfo);
    console.log(`Input pointer: ${inputStudentPtr}`);
    console.log(`Memory size: ${memory.buffer.byteLength} bytes`);
    console.log(`Memory buffer before calling:`, new Uint8Array(memory.buffer, inputStudentPtr, 64));

    //调用函数
    const startTime = performance.now();
    const outputStudentPtr = instance.exports[func](inputStudentPtr, ...args);
    const endTime = performance.now();
    console.log(`Output pointer: ${outputStudentPtr}`);
    console.log(`calculate time: ${(endTime - startTime)} ms`);

    if (outputStudentPtr < 0 || outputStudentPtr >= memory.buffer.byteLength) {
        console.error("Invalid output pointer!");
        return;
    }

    // 从内存中读取返回的 JSON 字符串
    console.log(`Memory buffer byte length:${(memory.buffer.byteLength)}`);


    const outputJsonString = (function() {
        const byteArray = new Uint8Array(memory.buffer, outputStudentPtr);
        let end = 0;
        // 查找终止符 `0` 来确定字符串的结束位置
        while (end < byteArray.length && byteArray[end] !== 0) {
            end++;
        }
        // 解码有效的 JSON 字符串部分
        return new TextDecoder('utf-8').decode(byteArray.subarray(0, end));
    })();
    console.log(`Output JSON string: ${outputJsonString}`);
    // 调用函数，传入 JSON 字符串
    const studentInfo1 = parseStudentJson(outputJsonString);

    // 输出结果
    console.log(`Parsed Student Object:${studentInfo1}` );
    //const outputStudent = JSON.parse(outputJsonString);
    //const outputStudent = imported.JSON_parse(outputJsonString);
    //console.log(`Output student:`, outputStudent);
 
}

const filepath = "build/object_json.wasm";
test(filepath, "withInputAndOutput");
